package org.shijiagen.search.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.xcontent.XContentType;
import org.shijiagen.doc.ProductDoc;
import org.shijiagen.param.ProductSearchParam;
import org.shijiagen.pojo.Product;
import org.shijiagen.search.service.SearchService;
import org.shijiagen.utils.R;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Service
@RequiredArgsConstructor
public class SearchServiceImpl implements SearchService {

    private final RestHighLevelClient restHighLevelClient;

    @Override
    public R search(ProductSearchParam productSearchParam) {
        SearchRequest searchRequest = new SearchRequest("product");
        String keyWord = productSearchParam.getSearch();
        if(StringUtils.hasText(keyWord)){
            // 传入的关键字不为空则根据关键字查询
            searchRequest.source().query(QueryBuilders.matchQuery("all",keyWord));
        }else {
            // 传入的关键字为空查询全部商品
            searchRequest.source().query(QueryBuilders.matchAllQuery());
        }
        searchRequest.source().from((productSearchParam.getCurrentPage()-1)*productSearchParam.getPageSize())
                .size(productSearchParam.getPageSize());
        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 查询出的结果数量
        long total = searchResponse.getHits().getTotalHits().value;
        // 查询出的结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        // 创建一个JSON转换器
        ObjectMapper objectMapper = new ObjectMapper();
        // 创建一个存放商品的线程安全的集合
        List<Product> result = Collections.synchronizedList(new ArrayList<>());
        // 遍历结果数组取出数据
        Arrays.stream(hits).parallel().forEach(hit -> {
            // 在结果集中取出对应商品的JSON字符串转成Product对象
            try {
                // TODO: 修改Product实体类，添加忽略没有的属性忽略的注解，否则这里的JSON字符串有all属性，强行转换成Product会报错
                result.add(objectMapper.reader().readValue(hit.getSourceAsString(),Product.class));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });

        return R.ok(null,result,total);
    }

    @Override
    public R save(Product product) {
        try {
            // 将商品对象转换成json字符串
            ObjectMapper objectMapper = new ObjectMapper();
            String productJson = objectMapper.writer().writeValueAsString(new ProductDoc(product));
            // 把转好的数据存到es索引中
            restHighLevelClient.index(new IndexRequest("product").id(product.getProductId().toString())
                            .source(productJson, XContentType.JSON),
                    RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return R.ok("数据同步成功!");
    }

    @Override
    public R remove(Product product) {
        try {
            restHighLevelClient.delete(new DeleteRequest("product").id(product.getProductId().toString()),
                    RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return R.ok("商品删除数据同步成功！");
    }
}
